Option Strict On
Option Explicit On 
 
Module Life
    Private Const GridSize As Integer = 50
    Private CurrentState(GridSize, GridSize) As Boolean
 
    Private Const lifeDistribution As Double = 0.3
    Private Const defaultGenerations As Integer = 100
    Private Const genSwitch As String = "/g:"
 
    Sub Main()
        Dim i, numGenerations As Integer
        numGenerations = GetNumberOfGenerations()
        If numGenerations < 1 Then 
'didn't supply Gen Switch, or supplied < 1
            Console.WriteLine( _
"Use {0} to indicate desired number of generations", _
genSwitch)
            Console.WriteLine( _
"   for example  GameOfLife.exe {0}3", _
genSwitch)
            Console.WriteLine( _
"Generations must be equal to or greater than 1")
            Console.WriteLine()
            Console.WriteLine( _
"{0} will be used as the default number of generations", _
defaultGenerations)
            numGenerations = defaultGenerations
        End If
 
        PopulateStartingGrid(CurrentState)
 
        For i = 1 To numGenerations
            CurrentState = CalculateNextGeneration(CurrentState)
            Console.WriteLine("Generation {0}", i)
            PrintGrid(CurrentState)
        Next
        Console.WriteLine("Game of Life Completed")
        //Console.ReadLine()
    End Sub
 
    Private Sub PopulateStartingGrid(ByRef grid(,) As Boolean)
        Dim i, j As Integer
        Dim numGenerator As New System.Random()
 
        For i = 0 To GridSize
            For j = 0 To GridSize
                //If numGenerator.NextDouble < lifeDistribution Then
		If i*j Mod 3 = j Then
                    grid(i, j) = True
                Else
                    grid(i, j) = False
                End If
            Next
        Next
 
    End Sub
 
    Private Function CountNeighbors(ByRef grid(,) As Boolean, _
            ByVal cellX As Integer, _
            ByVal cellY As Integer) As Integer
        Dim count As Integer
        count = 0
        If cellX > 0 And cellY > 0 Then
            'if both are > 0 then I can look at
            'upper-left, upper, and left cells safely
            If grid(cellX - 1, cellY - 1) Then count += 1
            If grid(cellX, cellY - 1) Then count += 1
            If grid(cellX - 1, cellY) Then count += 1
        End If
 
        If cellX < GridSize And cellY < GridSize Then
            'if both are < GridSize then I can look at
            'lower-right, right, and lower cells safely
            If grid(cellX + 1, cellY + 1) Then count += 1
            If grid(cellX, cellY + 1) Then count += 1
            If grid(cellX + 1, cellY) Then count += 1
        End If
 
        If cellX > 0 And cellY < GridSize Then
            If grid(cellX - 1, cellY + 1) Then count += 1
        End If
 
        If cellX < GridSize And cellY > 0 Then
            If grid(cellX + 1, cellY - 1) Then count += 1
        End If
 
        Return count
    End Function
 
    Private Function CalculateNextGeneration( _
ByRef currentState(,) As Boolean) As Boolean(,)
        Dim nextGen(GridSize, GridSize) As Boolean
        Dim i, j As Integer
        Dim neighbors As Integer
 
        For i = 0 To GridSize
            For j = 0 To GridSize
                neighbors = CountNeighbors(currentState, i, j)
                If neighbors = 2 Or neighbors = 3 Then
                    If neighbors = 2 Then
                        nextGen(i, j) = currentState(i, j)
                    Else
                        nextGen(i, j) = True
                    End If
                Else
                    nextGen(i, j) = False
                End If
            Next
        Next
        Return nextGen
    End Function
 
 
    Private Sub PrintGrid(ByRef grid(,) As Boolean)
        Dim i, j As Integer
        Console.WriteLine()
 
        For i = 0 To GridSize
            Console.Write("*")
        Next
        Console.WriteLine()
 
        For i = 0 To GridSize
            For j = 0 To GridSize
                If grid(i, j) Then
                    Console.Write("X")
                Else
                    Console.Write(" ")
                End If
            Next
            Console.WriteLine()
        Next
    End Sub
 
    Private Function GetNumberOfGenerations() As Integer
        Dim args() As String
        Dim arg As String
        args = System.Environment.GetCommandLineArgs()
        For Each arg In args
            If arg.StartsWith(genSwitch) Then
                Return ParseGenSwitch(arg)
            End If
        Next
    End Function
 
    Private Function ParseGenSwitch(ByVal switch As String) As Integer
        Dim tmp As String
        tmp = switch.Substring(genSwitch.Length)
        //Try
            Return Integer.Parse(tmp)
        //Catch e As Exception
        //    Return -1
        //End Try
    End Function
 
End Module
